package com.ruoyi.framework.aspectj;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.annotation.CompanyScope;
import com.ruoyi.common.annotation.DataScopePlus;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.context.PermissionContextHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Aspect
@Component
public class CompanyScopeAspect {
	
	/**
	 * 全部数据权限
	 */
	public static final String DATA_SCOPE_ALL = "1";
	
	/**
	 * 本部门所有作业点
	 */
	public static final String DATA_SCOPE_DEPT = "3";
	
	/**
	 * 本部门本作业点
	 */
	public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
	
	@Before("@annotation(controllerDataScope)")
	public void doBefore(JoinPoint point, CompanyScope controllerDataScope) throws Throwable {
		// clearDataScope(point);
		handleDataScope(point, controllerDataScope);
	}
	
	private void handleDataScope(JoinPoint point, CompanyScope controllerDataScope) {
		
		LoginUser loginUser = SecurityUtils.getLoginUser();
		if (StringUtils.isNotNull(loginUser)) {
			SysUser currentUser = loginUser.getUser();
			// 如果是超级管理员，则不过滤数据
			if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
				String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
				dataScopeFilter(point, currentUser, controllerDataScope.isCompanyScope(),
						controllerDataScope.isCfsScope(), permission);
			}
		}
		
	}
	
	private void dataScopeFilter(JoinPoint point, SysUser user, boolean companyScope, boolean cfsScope, String permission) {
		
		StringBuilder sqlString = new StringBuilder();
		List<String> conditions = new ArrayList<String>();
		
		for (SysRole role : user.getRoles()) {
			String dataScope = role.getDataScope();
			
			if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
					&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) {
				continue;
			}
			if (DATA_SCOPE_ALL.equals(dataScope)) {
				sqlString = new StringBuilder();
				conditions.add(dataScope);
				break;
			} else if ((DATA_SCOPE_DEPT.equals(dataScope) || DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) && companyScope && !cfsScope) {
				// 只查询码头数据 当表里面无cfs_cod字段时可使用该条逻辑
				System.out.println("只查询码头数据 当表里面无cfs_cod字段时可使用该条逻辑");
				sqlString.append(StringUtils.format(" OR company_cod = '{}' ", user.getCompanyCod()));
			} else if (DATA_SCOPE_DEPT.equals(dataScope) && companyScope && cfsScope) {
				// 只查询码头数据 就算有cfs_cod , 也只查询company_cod
				System.out.println("只查询码头数据 就算有cfs_cod , 也只查询company_cod");
				sqlString.append(StringUtils.format(" OR company_cod = '{}' ", user.getCompanyCod()));
			} else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope) && companyScope && cfsScope) {
				// 本码头本作业点数据
				// 将 user.getCfsCode() 用 , 分割成 String[]
				System.out.println("本码头本作业点数据");
				if (StringUtils.isNotEmpty(user.getCfsCod())) {
					// 如果用户有指定作业点，则只显示指定作业点的数据
					String[] cfsCodeArray = Convert.toStrArray(user.getCfsCod());
					
					String str = "";
					
					for (int i = 0; i < cfsCodeArray.length; i++) {
						str += "'" + cfsCodeArray[i] + "',";
					}
					
					sqlString.append(StringUtils.format(" OR ( company_cod = '{}' and cfs_cod in ({}) )", user.getCompanyCod(), str.substring(0, str.length() - 1)));
				} else {
					// 否则显示company_cod为该码头 但是 cfs_cod 为0的数据
					sqlString.append(StringUtils.format(" OR ( company_cod = '{}' and cfs_cod = '{}' )", user.getCompanyCod(), "0"));
				}
				
			}
			
			conditions.add(dataScope);
		}
		
		// 多角色情况下，所有角色都不包含传递过来的权限字符，这个时候sqlString也会为空，所以要限制一下,不查询任何数据
		if (StringUtils.isEmpty(conditions)) {
			sqlString.append(StringUtils.format(" OR company_cod = {} ", "0"));
		}
		
		if (StringUtils.isNotBlank(sqlString.toString())) {
			Object params = point.getArgs()[0];
			if (StringUtils.isNotNull(params) && params instanceof QueryWrapper) {
				((QueryWrapper<?>) params).apply(sqlString.substring(4));
			}
		}
		
	}
	
}
